package com.imooc.retrofit;

import com.google.gson.Gson;
import com.imooc.base.retrofit.http.GET;
import com.imooc.base.retrofit.http.POST;
import com.imooc.base.retrofit.http.Query;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import okhttp3.ResponseBody;

public class ServiceMethod {
    final Retrofit retrofit;
    final Method method;
    private String relativeUrl;
    private String httpMethod;
    final ParameterHandler<?>[] parameterHandlers;

    public ServiceMethod(Builder builder) {
        this.retrofit = builder.retrofit;
        this.method = builder.method;
        this.relativeUrl = builder.relativeUrl;
        this.httpMethod = builder.httpMethod;
        this.parameterHandlers = builder.parameterHandlers;
    }

    public Call createNewCall(Object[] args){
        RequestBuilder requestBuilder = new RequestBuilder(retrofit.baseUrl, relativeUrl, httpMethod, parameterHandlers, args);
        return retrofit.callFactory.newCall(requestBuilder.build());
    }

    public <T> T parseBody(ResponseBody responseBody) {

        // 返回值对象
        Type returnType = method.getGenericReturnType();
        Type type = ((ParameterizedType) returnType).getActualTypeArguments()[0];

        Gson gson = new Gson();
        return gson.fromJson(responseBody.charStream(),type);
    }

    public static class Builder {

        final Retrofit retrofit;
        final Method method;
        final Annotation[] methodAnnotations;
        private String relativeUrl;
        private String httpMethod;
        Annotation[][] parameterAnnotations;
        final ParameterHandler<?>[] parameterHandlers;

        public Builder(Retrofit retrofit, Method method) {
            this.retrofit=retrofit;
            this.method = method;
            methodAnnotations = method.getAnnotations();
            parameterAnnotations = method.getParameterAnnotations();
            parameterHandlers = new ParameterHandler[parameterAnnotations.length];
        }

        public ServiceMethod build(){
            // 解析 Okhttp 请求的时候 , url = baseUrl + relativeUrl , method
            for (Annotation annotation : methodAnnotations) {
                // 解析POST ,GET
                parseAnnotationMethod(annotation);
            }

            // 解析参数注解
            int count = parameterHandlers.length;
            for (int i = 0; i < count; i++) {
                Annotation annotation = parameterAnnotations[i][0];

                if (annotation instanceof Query){
                    // 封装成 ParameterHandler , 不同的参数注解选择不同的策略
                    parameterHandlers[i] = new ParameterHandler.Query<>(((Query) annotation).value());
                }
            }



            return new ServiceMethod(this);
        }

        private void parseAnnotationMethod(Annotation annotation) {
            if (annotation instanceof GET) {
                parseMethodAndPath("GET",((GET) annotation).value());
            }else if (annotation instanceof POST){
                parseMethodAndPath("POST",((POST) annotation).value());
            }
        }

        private void parseMethodAndPath(String method, String value) {
            this.httpMethod = method;
            this.relativeUrl = value;
        }
    }
}
